package com.nf.factory;


import com.nf.Annotation.Autowired;
import com.nf.Annotation.ClassAnnotation;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 扫描类得到所有的全限定类名
 * ClassAnnotation("jianzhi")初始化map集合  单例：map 键值 对象  或者 存放类信息 map  键值 类信息（class元对象）
 * 从map里拿对象  action  private Service service=null；
 * 注入：@Autowirte("serviceimp") serviceimp dao
 */


/**
 * 添加依赖
 */
public class Assignment {
    //对外访问的方法
    public static <T> T fun(String jianzhi){
        Object init = init(jianzhi);
        return (T)init;
    }

    /**
     *拿到被注入依赖后的对象
     */
    private static <T> T init(String jianzhi) {
        List<String> init = ScanUtil.getClassNames();
        //拿到测试类想取出类的元对象
        Class<?> beanName = getBeanName(init, jianzhi);
        //通过工场拿到它的实例
        Object bean1 = NewBean.getBean(beanName);
        //注入
        zhuru(init,bean1);
        return (T)bean1;
    }
    private static void zhuru(List<String> init , Object bean1){
        try {
            //给它的字段注入依赖
            fieldInjection(init, bean1);
            //给它的方法注入依赖
            methodInjection(init,bean1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 注入依赖
     * 参数1：所有的包名
     * 参数2：测试类想要得到类的实例(注入递归的时候不能实例化，所以必须传对象)
     */
    private static void fieldInjection(List<String> init , Object bean1) throws Exception{
        //获取他的元对象
        Class<?> beanName = bean1.getClass();
        //获取要注入类的所有字段
        Field[] declaredField = beanName.getDeclaredFields();
        for(int i=0;i<declaredField.length;i++){
            if(declaredField[i].isAnnotationPresent(Autowired.class)){
                //注入对象的键值
                String value = declaredField[i].getAnnotation(Autowired.class).value();
                //通过注释取对应的Class<?>值
                Class<?> injection = getBeanName(init, value);
                //要注入的实例化对象
                Object bean = NewBean.getBean(injection);
                declaredField[i].setAccessible(true);
                //赋值
                declaredField[i].set(bean1,bean);
                zhuru(init,bean);
            }
        }
    }

    /**
     * 通过方法注入依赖
     * 参数1：所有的包名
     * 参数2：测试类想要得到类的实例
     */
    private static void methodInjection(List<String> init,Object bean1) throws Exception {
        //获取他的元对象
        Class<?> beanName = bean1.getClass();
        //获取要注入类的所有方法
        Method[] declaredMethods = beanName.getDeclaredMethods();
        for(int i=0;i<declaredMethods.length;i++){
            if(declaredMethods[i].isAnnotationPresent(Autowired.class)){
                String value = declaredMethods[i].getAnnotation(Autowired.class).value();
                //要注入的元对象
                Class<?> beanName1 = getBeanName(init,value);
                //通过工场实例化要注入的元对象
                Object bean = NewBean.getBean(beanName1);
                declaredMethods[i].setAccessible(true);
                declaredMethods[i].invoke(bean1,bean);
                zhuru(init,bean);
            }
        }

    }
   /* test.action.UserAction
    test.dao.UserDao
    test.dao.UserDaoImpl
    test.entity.User
    test.service.UserService
    test.service.UserServiceImpl
    test.util.DBUtil*/

    /**
     *通过注释取Class<?>值
     */
    private static Class<?> getBeanName(List<String> init,String strs){
        Class<?> clazz = null;
        Class<?> returnclazz = null;
        //把传来的值的首字母大写，变为一个简单类名
        String st=strs.substring(0, 1).toUpperCase() + strs.substring(1);
        for(String str:init) {
            try {
                clazz = Class.forName(str);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            if(clazz.isAnnotationPresent(ClassAnnotation.class)&&(clazz.getAnnotation(ClassAnnotation.class).value()).equals(strs)){
                returnclazz=clazz;
            }else if(str.contains(st)){
                returnclazz=clazz;
            }
        }
        return returnclazz;
    }
}
